﻿using Microsoft.Extensions.Options;
using System;
using System.Text.Json;

namespace Fast
{
    public class FastSystemTextJsonSerializerProvider : IJsonSerializerProvider
    {
        protected FastSystemTextJsonSerializerOptions Options { get; }
        public FastSystemTextJsonSerializerProvider(IOptions<FastSystemTextJsonSerializerOptions> options)
        {
            Options = options?.Value ?? throw new ArgumentNullException(nameof(options));
        }

        /// <summary>
        /// 序列化成 Json 字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="camelCase">是否采用驼峰命名法</param>
        /// <param name="indented">是否缩进</param>
        /// <returns></returns>
        public string Serialize(object obj, bool camelCase = true, bool indented = false)
        {
            return JsonSerializer.Serialize(obj, CreateJsonSerializerOptions(camelCase, indented));
        }

        /// <summary>
        /// 反序列化成指定类型对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonString">目标Json字符串</param>
        /// <param name="camelCase">是否采用驼峰命名法</param>
        /// <returns></returns>
        public T Deserialize<T>(string jsonString, bool camelCase = true)
        {
            return JsonSerializer.Deserialize<T>(jsonString, CreateJsonSerializerOptions(camelCase));
        }

        /// <summary>
        /// 反序列化成 <see cref="Type"/> 类型的 <see cref="object"/> 对象。得到结果后可以显示转换为 <see cref="Type"/> 类型
        /// </summary>
        /// <param name="type"></param>
        /// <param name="jsonString">目标Json字符串</param>
        /// <param name="camelCase">是否采用驼峰命名法</param>
        /// <returns></returns>
        public object Deserialize(Type type, string jsonString, bool camelCase = true)
        {
            return JsonSerializer.Deserialize(jsonString, type, CreateJsonSerializerOptions(camelCase));
        }

        protected virtual JsonSerializerOptions CreateJsonSerializerOptions(bool camelCase = true, bool indented = false)
        {
            var settings = new JsonSerializerOptions(Options.JsonSerializerOptions);

            settings.PropertyNamingPolicy = camelCase ? JsonNamingPolicy.CamelCase : null;

            if (indented)
            {
                settings.WriteIndented = true;
            }

            return settings;
        }
    }
}
